package com.cl.code.database.mybatis.module.sql.method;

import com.cl.code.database.mybatis.constant.CLMybatisConstants;
import com.cl.code.database.mybatis.module.sql.table.TableField;
import com.cl.code.database.mybatis.module.sql.table.TableInfo;
import com.cl.code.database.mybatis.util.SqlScriptUtils;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.parsing.GenericTokenParser;
import org.apache.ibatis.session.Configuration;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author chengliang
 * @since 1.0.0
 */
public class CLList extends AbstractSqlMethod {

    public CLList(Class<?> type, Method method, TableInfo tableInfo, Configuration configuration) {
        super(type, method, tableInfo, configuration);
    }

    @Override
    public SqlCommandType getSqlCommandType() {
        return SqlCommandType.SELECT;
    }

    @Override
    public Class<?> getResultType() {
        return tableInfo.getEntityClass();
    }

    @Override
    protected String buildSql() {
        String sql = "SELECT #{view} FROM #{tn} #{where} #{order}";
        Map<String, String> map = new HashMap<>();
        map.put("tn", tableInfo.getTableName());
        map.put("view", getViewSql());
        map.put("where", getWhereSql());
        map.put("order", getOrderSql());
        sql = new GenericTokenParser(CLMybatisConstants.PARAM_START, CLMybatisConstants.PARAM_END, map::get).parse(sql);
        return SqlScriptUtils.convertScript(sql);
    }

    public String getViewSql() {
        String viewSqlParam = CLMybatisConstants.VIEW_PARAM_NAME + "." + CLMybatisConstants.VIEW_SQL;
        String viewSqlPlaceholder = "${" + viewSqlParam + "}";
        TableField[] fieldItems = tableInfo.getTableFields();
        String fields = Arrays.stream(fieldItems).map(TableField::getSqlFieldName).collect(Collectors.joining(", "));
        return SqlScriptUtils.convertChoose(CLMybatisConstants.VIEW_PARAM_NAME + " != null and " + viewSqlParam + " != null and " + viewSqlParam + " != ''", viewSqlPlaceholder, fields);
    }

    public String getOrderSql() {
        String orderSqlParam = CLMybatisConstants.ORDER_PARAM_NAME + "." + CLMybatisConstants.ORDER_SQL;
        String orderSqlPlaceholder = "${" + orderSqlParam + "}";
        return SqlScriptUtils.convertIf(CLMybatisConstants.ORDER_PARAM_NAME + " != null and " + orderSqlParam + " != null and " + orderSqlParam + " != ''", "ORDER BY " + orderSqlPlaceholder, true);
    }

}
